var iCor;
var Task = function(id, func, datajs, callback, url, method, options) {
	// its id
	this.id = id;
	// branch flag for native code.
	this.func = func,
	// Native code will call this method to get the query string.
	this.datajs = datajs;
	// after native code retrieve the data from other layer, the js function that native want to call
	this.callback = callback;
	// the URL the request pointing to
	this.url = url;
	this.method = method;
	// use 'post' or 'get'
	this.options = options;
}
var Delegate = function() {
	var tasks = [];
	// the references that can be retrieved by id
	var processedTasks = [];
	// empty resolved deferred objects
	var deferred = $.when();

	// handle the next object
	this.handleNextTask = function() {
		// if the current deferred task has resolved and there are more tasks
		if (deferred.state() == "resolved" && tasks.length > 0) {
			var task = tasks.shift();
			// keep the task in the processed task queue.
			processedTasks.push(task);
			// set the deferred object when set it to be an empty deferred object.
			deferred = multipleRequestDelegate.makeCall(task);
			// cannot get a deferred object, asign it with an empty resolved one
			if (!(deferred && deferred.promise)) {
				deferred = $.when();
			} else {
				// handle the next one when the current one is done.
				deferred.done(multipleRequestDelegate.handleNextTask);
				task.deferred = deferred;
			}
		}
	};

	this.append = function(options) {
		var id = getUniqueId();
		var func = "MultipleProxy";
		var datajs = "iMobile.multipleRequestMessageJSHandler";
		var callback = 'iMobile.multipleCallbackHandler';
		var url = "";
		if (options.url != undefined && options.url != '') {
			url = options.url;
		} else {
			url = iCor.apis[options.name].url;
			if (typeof (url) == 'object') {
				url = url[window.locale];
			}
		}
		url = iCor.getUrl(url);
		
		var method = options.method;

		var task = new Task(id, func, datajs, callback, url, method, options);
		console.log("task's content = %o", task);
		tasks.push(task);
		this.handleNextTask();
	};

	this.makeCall = function(task) {
		var deferred = $.Deferred();
			
		window.onhashchange = function() {
			console.log("onhashchange");
		}
		console.log("hsbc://function=" + task.func + "&datajs=" + task.datajs + "&callbackjs=" + task.callback + "&url=" + task.url +"&method=" + task.method + "&taskId=" + task.id.toString());
		location.href = "hsbc://function=" + task.func + "&datajs=" + task.datajs + "&callbackjs=" + task.callback + "&url=" + task.url + "&method=" + task.method + "&taskId=" + task.id.toString();
		
		return deferred;
	};

	this.getTasks = function() {
		return tasks;
	};

	this.getProcessedTasks = function() {
		return processedTasks;
	};

	this.removeProcessedTaskAt = function(index) {
		// TODO find a better way to do this
		var i;
		if (index < processedTasks.length) {
			for ( i = index; i < processedTasks.length - 1; i++) {
				processedTasks[i] = processedTasks[i + 1];
			}
			processedTasks.length = processedTasks.length - 1;
		}
	};

	this.getProcessedTaskIndexById = function(id) {
		for ( i = 0; i < processedTasks.length; i++) {
			var tsk = processedTasks[i];
			if (tsk.id.toString() == id) {
				return i;
			}
		}

		return -1;
	};

	this.getProcessedTaskById = function(id) {
		for ( i = 0; i < processedTasks.length; i++) {
			var tsk = processedTasks[i];
			if (tsk.id.toString() == id) {
				return tsk;
			}
		}
	};
}

$.fn.multipleRequestProxy = {
	multipleRequest : function(options,obj) {
		iCor = obj;
		var options = options || {};
		if (options.showLoadingFlag!=false) {
			try {
				iCor.showLoadingMask(options.loadingMsg||'');
			} catch(e) {
				window.alert("iCor.showLoadingMask");
			}
		}
		multipleRequestDelegate.append(options);
	}
}

function getUniqueId() {
	var S4 = function() {
		return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
	}
	return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}

var multipleRequestDelegate = new Delegate();